import time, random
from machine import Pin
from machine import PWM
import utime

# 蜂鸣器引脚（无源蜂鸣器）
buzzer = PWM(Pin(14), freq=440, duty=0)  # 初始频率为 440 Hz（A4），占空比为 0（静音）

# 音符频率表（单位：Hz）
notes = {
    "C4": 262, "D4": 294, "E4": 330, "F4": 349, "G4": 392,
    "A4": 440, "B4": 494, "C5": 523, "D5": 587, "E5": 659,
    "F5": 698, "G5": 784, "A5": 880, "B5": 988
}

# 音效模式
sound_patterns = {
    "start_game": [("E5", 150), ("C5", 150)],  # 游戏开始：简短的两个音符
    "eat_food": [("E4", 100), ("G4", 100)],    # 吃到果实：短促的两声
    "hit_wall": [("C4", 200)],                 # 撞到墙：低沉的长响
    # 其他音效模式可以根据需要添加
}

def play_sound(state):
    """根据状态播放蜂鸣器声音"""
    if state in sound_patterns:
        for note, duration in sound_patterns[state]:
            if note in notes:  # 检查音符是否有效
                buzzer.freq(notes[note])  # 设置频率
                buzzer.duty(512)  # 设置占空比（50%）
                utime.sleep_ms(duration)  # 持续发声
                buzzer.duty(0)  # 停止发声
                utime.sleep_ms(50)  # 音符间隔

def run(ed, k_u, k_d, k_l, k_r, k_a, k_b):
    snake = [(5, 5), (4, 5), (3, 5)]  # 蛇初始位置
    direction = (1, 0)  # 初始方向
    food = (random.randint(0, 15), random.randint(0, 9))  # 食物初始位置
    score = 0  # 得分初始化

    # 初始化蜂鸣器
    play_sound("start_game")  # 添加游戏开始音效
    buzzer.duty(0)  # 确保蜂鸣器静音

    while True:
        # 更新方向
        new_direction = direction
        if k_u.value() == 0:
            new_direction = (0, -1)
        elif k_d.value() == 0:
            new_direction = (0, 1)
        elif k_l.value() == 0:
            new_direction = (-1, 0)
        elif k_r.value() == 0:
            new_direction = (1, 0)
        # 防止蛇反向移动
        if (new_direction[0], new_direction[1]) != (-direction[0], -direction[1]):
            direction = new_direction
        # 移动蛇
        new_head = (snake[0][0] + direction[0], snake[0][1] + direction[1])
        snake.insert(0, new_head)
        # 判断是否吃到食物
        if new_head == food:
            play_sound("eat_food")  # 播放吃到食物音效
            food = (random.randint(0, 15), random.randint(0, 9))
            score += 1  # 增加得分
        else:
            snake.pop()
        # 检测碰撞
        head = snake[0]
        if (
            head[0] < 0
            or head[0] >= 16
            or head[1] < 0
            or head[1] >= 10
            or head in snake[1:]
        ):
            play_sound("hit_wall")  # 撞到墙或自身时播放音效
            break
        # 绘制游戏画面
        ed.fill(0x0000)  # 清屏
        ed.rect(0, 20, 160, 108, 0xFFFF)  # 绘制边界
        # 绘制蛇
        for segment in snake:
            ed.fill_rect(
                segment[0] * 10, segment[1] * 10 + 20, 9, 9, 0x07E0
            )  # 绿色蛇身
        # 绘制食物
        ed.fill_rect(food[0] * 10, food[1] * 10 + 20, 9, 9, 0xF800)  # 红色食物
        # 显示得分
        ed.text("得分: {}".format(score), 5, 5)  # 显示得分
        ed.show()
        time.sleep(0.2)  # 控制蛇的移动速度
    # 游戏结束显示
    ed.fill(0x0000)
    ed.text("游戏结束!", 50, 20)
    ed.text("得分: {}".format(score), 50, 50)
    ed.text("按 B 键返回", 80, 110)
    ed.show()
    # 等待按下 B 键返回
    while True:
        if k_b.value() == 0:
            time.sleep(0.2)
            return